package com.myersinfosys.protrack.vfs;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.auth.StaticUserAuthenticator;
import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
import org.apache.commons.vfs.provider.ftp.FtpFileSystemConfigBuilder;
import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
import org.apache.commons.vfs.provider.url.UrlFileName;

/** FileSession - Public class handling a connection to a file system.
*
* @author E.Morris
* @version 4/15/2011
*/
public class FileSession {

	private FileSessionManager manager = null;
	private Log log = LogFactory.getLog(this.getClass());
	private FileObject parent=null;
	private FileObject child=null;
	
	
	@SuppressWarnings("unused")
	private FileSession() {
	}
	
	public FileSession(FileSessionManager manager) {
		setSessionManager(manager);
	}
	
	public FileSession(FileSessionManager manager, String sessionName, String envName) {
		setSessionManager(manager);
		openFileSession(sessionName, envName);
	}
	
	public FileSession(FileSessionManager manager, String sessionName) {
		setSessionManager(manager);
		openFileSession(sessionName, null);
	}
	
	private void setSessionManager(FileSessionManager manager) {
		this.manager = manager;
	}
	public FileSessionManager getSessionManager() {
		return this.manager;
	}
	
	
	public boolean openFileSession(String sessionName) {
		return openFileSession(sessionName, null);
	}
	
	public boolean openFileSession(String sessionName, String envName) {
		
        String scheme=null;
        String user=null;
        String pw=null;
        String host=null;
        int port=-1;
        String path=null;
        String filename=null;
        boolean success=false;
        
        try {
        	// todo: get configurable session settings from secure file
	        if(sessionName.equals("localtemp")) {
	        	scheme = "file";
	        	path = System.getProperty("java.io.tmpdir");
	        }
	        if(sessionName.equals("localenv")) {
	        	scheme = "file";
	        	path = System.getenv(envName);
	        }	        
	        if(sessionName.equals("mytestftp")) {
	        	scheme = "ftp";
	        	user = "ftptest";
	        	pw = "release";
	        	host = "127.0.0.1";
	        	path = "/";
	        }
	        if(sessionName.equals("myersftp")) {
	        	scheme = "ftp";
	        	user = "emorris";
	        	pw = "release";
	        	host = "192.168.0.118";
	        	path = "/home/emorris/";
	        }	        
	        if(sessionName.equals("myremoteftp")) {
	        	scheme = "ftp";
	        	user = "ftptest@bonmotter.com";
	        	pw = "release";
	        	//host = "bonmotter.com";
	        	host = "69.175.71.58";
	        	path = "/";
	        }	        
	        if(sessionName.equals("mytestsmb")) {
	        	scheme = "smb";
	        	user = "Guest";
	        	pw = null;
	        	host = "HOME-PC";
	        	path = "/smbtest";
	        }	        	        
	        
	        
	        FileObject parentObj = getFileHandle(scheme, user, pw, host, port, path, filename);
	        
	        setParent(parentObj);
	        
	        success = (parent!=null);
	        
		} catch (FileSystemException e) {
			e.printStackTrace();
		}
		
		return success;		
	}
	
	
	public void closeFileSession() {
		closeChild();
		closeParent();
	}

	
	public void closeParent() {
		setParent(null);
	}
	
	
	public void closeChild() {
		setChild(null);
	}

	
	public FileObject getChild() {
		return this.child;
	}

	
	public FileObject getParent() {
		return this.parent;
	}

	private void setParent(FileObject fo) {
		if(parent!=null) {
			try {
				parent.close();
			} catch (FileSystemException e) {
				e.printStackTrace();
			}
		}
		parent = fo;
	}	
	
	public void setChild(String fileName) {
		try {
			if(child!=null || fileName==null) {
				child.close();
				child=null;
			}	
			
			if(parent!=null && fileName!=null) {
				child = parent.resolveFile(fileName);
			}
			
		} catch (FileSystemException e) {
			e.printStackTrace();
		}	
	}

	
	private FileObject getFileHandle(String provider, String user, String pw,
			String host, int port, 
			String path, String filename) throws FileSystemException {

		FileObject fileObject = null;

		if(manager.hasProvider(provider)) {

			String uri = null;
			FileSystemOptions opts = new FileSystemOptions();
			StaticUserAuthenticator auth = null;

			if(user!=null) {
				auth = new StaticUserAuthenticator(null, user, pw);
				DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
			}

			if(auth != null) {
				user = null;
				pw = null;
				getLogger().info("Secure log in");
			} else {
				getLogger().warn("Insecure log in");
			}
			uri = createFullURL(
					provider, 
					user, pw,
					host, port,
					path);

			if(filename != null) {
				uri = uri + "/" + filename;
			}


			if(provider.equals("ftp")) {
				FtpFileSystemConfigBuilder.getInstance().setPassiveMode(opts, true);
				// todo: need to set binary mode? if so, how?
			}
			if(provider.equals("sftp")) {
				SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
			}

			//System.out.println(uri + "/" + filename);
			fileObject = manager.resolveFile(uri, opts);
		}

		return fileObject;
	}	

	
	private Log getLogger() {
		return this.log;
	}	
	
	//fully qualified URL used for vfs
	// scheme://[ user [: pw ]@] host [: port ][ absolute-path ] 
	private String createFullURL(
	         final String scheme,
	         final String user,
	         final String pw,
	         final String host,
	         int port,
	         final String path) {
			
		UrlFileName url = 
			new UrlFileName(scheme, host, port, -1, user, pw, path, FileType.FILE, null);
		
		return url.toString();
	}	
}
